package com.fr.base.core.antlr;

import com.fr.base.core.antlr.collections.AST;
import com.fr.base.core.antlr.collections.impl.ASTArray;
import java.io.PrintStream;
import java.lang.reflect.Constructor;
import java.util.Hashtable;

public class ASTFactory
{
  protected String theASTNodeType = null;
  protected Class theASTNodeTypeClass = null;
  protected Hashtable tokenTypeToASTClassMap = null;

  public ASTFactory()
  {
  }

  public ASTFactory(Hashtable paramHashtable)
  {
    setTokenTypeToASTClassMap(paramHashtable);
  }

  public void setTokenTypeASTNodeType(int paramInt, String paramString)
    throws IllegalArgumentException
  {
    if (this.tokenTypeToASTClassMap == null)
      this.tokenTypeToASTClassMap = new Hashtable();
    if (paramString == null)
    {
      this.tokenTypeToASTClassMap.remove(new Integer(paramInt));
      return;
    }
    Class localClass = null;
    try
    {
      localClass = Utils.loadClass(paramString);
      this.tokenTypeToASTClassMap.put(new Integer(paramInt), localClass);
    }
    catch (Exception localException)
    {
      throw new IllegalArgumentException("Invalid class, " + paramString);
    }
  }

  public Class getASTNodeType(int paramInt)
  {
    if (this.tokenTypeToASTClassMap != null)
    {
      Class localClass = (Class)this.tokenTypeToASTClassMap.get(new Integer(paramInt));
      if (localClass != null)
        return localClass;
    }
    if (this.theASTNodeTypeClass != null)
      return this.theASTNodeTypeClass;
    return CommonAST.class;
  }

  public void addASTChild(ASTPair paramASTPair, AST paramAST)
  {
    if (paramAST != null)
    {
      if (paramASTPair.root == null)
        paramASTPair.root = paramAST;
      else if (paramASTPair.child == null)
        paramASTPair.root.setFirstChild(paramAST);
      else
        paramASTPair.child.setNextSibling(paramAST);
      paramASTPair.child = paramAST;
      paramASTPair.advanceChildToEnd();
    }
  }

  public AST create()
  {
    return create(0);
  }

  public AST create(int paramInt)
  {
    Class localClass = getASTNodeType(paramInt);
    AST localAST = create(localClass);
    if (localAST != null)
      localAST.initialize(paramInt, "");
    return localAST;
  }

  public AST create(int paramInt, String paramString)
  {
    AST localAST = create(paramInt);
    if (localAST != null)
      localAST.initialize(paramInt, paramString);
    return localAST;
  }

  public AST create(int paramInt, String paramString1, String paramString2)
  {
    AST localAST = create(paramString2);
    if (localAST != null)
      localAST.initialize(paramInt, paramString1);
    return localAST;
  }

  public AST create(AST paramAST)
  {
    if (paramAST == null)
      return null;
    AST localAST = create(paramAST.getType());
    if (localAST != null)
      localAST.initialize(paramAST);
    return localAST;
  }

  public AST create(Token paramToken)
  {
    AST localAST = create(paramToken.getType());
    if (localAST != null)
      localAST.initialize(paramToken);
    return localAST;
  }

  public AST create(Token paramToken, String paramString)
  {
    AST localAST = createUsingCtor(paramToken, paramString);
    return localAST;
  }

  public AST create(String paramString)
  {
    Class localClass = null;
    try
    {
      localClass = Utils.loadClass(paramString);
    }
    catch (Exception localException)
    {
      throw new IllegalArgumentException("Invalid class, " + paramString);
    }
    return create(localClass);
  }

  protected AST createUsingCtor(Token paramToken, String paramString)
  {
    Class localClass = null;
    AST localAST = null;
    try
    {
      localClass = Utils.loadClass(paramString);
      Class[] arrayOfClass = { Token.class };
      try
      {
        Constructor localConstructor = localClass.getConstructor(arrayOfClass);
        localAST = (AST)localConstructor.newInstance(new Object[] { paramToken });
      }
      catch (NoSuchMethodException localNoSuchMethodException)
      {
        localAST = create(localClass);
        if (localAST != null)
          localAST.initialize(paramToken);
      }
    }
    catch (Exception localException)
    {
      throw new IllegalArgumentException("Invalid class or can't make instance, " + paramString);
    }
    return localAST;
  }

  protected AST create(Class paramClass)
  {
    AST localAST = null;
    try
    {
      localAST = (AST)paramClass.newInstance();
    }
    catch (Exception localException)
    {
      error("Can't create AST Node " + paramClass.getName());
      return null;
    }
    return localAST;
  }

  public AST dup(AST paramAST)
  {
    if (paramAST == null)
      return null;
    AST localAST = create(paramAST.getClass());
    localAST.initialize(paramAST);
    return localAST;
  }

  public AST dupList(AST paramAST)
  {
    AST localAST1 = dupTree(paramAST);
    for (AST localAST2 = localAST1; paramAST != null; localAST2 = localAST2.getNextSibling())
    {
      paramAST = paramAST.getNextSibling();
      localAST2.setNextSibling(dupTree(paramAST));
    }
    return localAST1;
  }

  public AST dupTree(AST paramAST)
  {
    AST localAST = dup(paramAST);
    if (paramAST != null)
      localAST.setFirstChild(dupList(paramAST.getFirstChild()));
    return localAST;
  }

  public AST make(AST[] paramArrayOfAST)
  {
    if ((paramArrayOfAST == null) || (paramArrayOfAST.length == 0))
      return null;
    AST localAST1 = paramArrayOfAST[0];
    AST localAST2 = null;
    if (localAST1 != null)
      localAST1.setFirstChild(null);
    for (int i = 1; i < paramArrayOfAST.length; ++i)
    {
      if (paramArrayOfAST[i] == null)
        break label122:
      if (localAST1 == null)
      {
        localAST1 = localAST2 = paramArrayOfAST[i];
      }
      else if (localAST2 == null)
      {
        localAST1.setFirstChild(paramArrayOfAST[i]);
        localAST2 = localAST1.getFirstChild();
      }
      else
      {
        localAST2.setNextSibling(paramArrayOfAST[i]);
      }
      for (localAST2 = localAST2.getNextSibling(); localAST2.getNextSibling() != null; localAST2 = localAST2.getNextSibling());
    }
    label122: return localAST1;
  }

  public AST make(ASTArray paramASTArray)
  {
    return make(paramASTArray.array);
  }

  public void makeASTRoot(ASTPair paramASTPair, AST paramAST)
  {
    if (paramAST != null)
    {
      paramAST.addChild(paramASTPair.root);
      paramASTPair.child = paramASTPair.root;
      paramASTPair.advanceChildToEnd();
      paramASTPair.root = paramAST;
    }
  }

  public void setASTNodeClass(Class paramClass)
  {
    if (paramClass != null)
    {
      this.theASTNodeTypeClass = paramClass;
      this.theASTNodeType = paramClass.getName();
    }
  }

  public void setASTNodeClass(String paramString)
  {
    this.theASTNodeType = paramString;
    try
    {
      this.theASTNodeTypeClass = Utils.loadClass(paramString);
    }
    catch (Exception localException)
    {
      error("Can't find/access AST Node type" + paramString);
    }
  }

  /**
   * @deprecated
   */
  public void setASTNodeType(String paramString)
  {
    setASTNodeClass(paramString);
  }

  public Hashtable getTokenTypeToASTClassMap()
  {
    return this.tokenTypeToASTClassMap;
  }

  public void setTokenTypeToASTClassMap(Hashtable paramHashtable)
  {
    this.tokenTypeToASTClassMap = paramHashtable;
  }

  public void error(String paramString)
  {
    System.err.println(paramString);
  }
}